import { CreateStockDto } from './../stock/dto/create-stock.dto';
import { SearchProduct } from './dto/search-product.dto';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { CreateProductDto } from './dto/create-product.dto';
import { UpdateProductDto } from './dto/update-product.dto';
import { Repository } from 'typeorm';
import { Product } from './entities/product.entity';
import { Category, getCategory, getSource, Source, getStatus, Status } from './enum/Enum';
import Utils from 'src/utils/Utils';
import { Stock } from 'src/server/stock/entities/stock.entity';

@Injectable()
export class ProductService {
  ip = [
    '排球少年',
    '蓝色监狱',
    '文豪野犬',
    '名侦探柯南',
    '第五人格',
    '葬送的芙莉莲',
    '初音未来',
    '咒术回战',
    '宫崎骏',
    '恋与深空',
    '偶像梦幻祭',
    '灵能百分百',
    '光与夜之恋',
    '间谍过家家',
    '盗墓笔记',
    '防风铃',
  ]
  constructor(
    @InjectRepository(Product)
    private product: Repository<Product>,
    @InjectRepository(Stock)
    private stock: Repository<Stock>,
  ) { }

  async create(createProductDto: CreateProductDto) {
    createProductDto.pId = Utils.guid()
    if (createProductDto.stock) {
      const obj = new CreateStockDto()
      obj.type = 0
      obj.guid = Utils.guid()
      obj.creatorGuid = createProductDto.creatorGuid
      obj.pId = createProductDto.pId
      obj.price = createProductDto.buyPrice
      obj.total = createProductDto.stock
      obj.postage = createProductDto.postage
      obj.sum = obj.total * obj.price
      await this.stock.save(obj)
    }
    return this.product.save(createProductDto)
  }

  formatResult(list: Product[]) {
    return list.forEach(_ => {
      _.categoryDesc = getCategory(_.category)
      _.sourceDesc = getSource(_.source)
      _.statusDesc = getStatus(_.status)
    })
  }

  async findAllByNoCondition() {
    const result = await this.product.find()
    this.formatResult(result)
    return result
  }

  async findAll(p: SearchProduct) {
    const { page, pageSize } = p
    const queryBuilder = this.product.createQueryBuilder('p')
    queryBuilder.andWhere('p.delete = :delete', { delete: false })

    if (p.name) {
      queryBuilder.andWhere('p.p_name LIKE :name', { name: `%${p.name}%` })
    }
    if (p.pIp) {
      queryBuilder.andWhere('p.p_ip LIKE :pIp', { pIp: `%${p.pIp}%` })
    }
    if (p.category) {
      queryBuilder.andWhere('p.category = :category', { category: p.category })
    }
    if (p.source) {
      queryBuilder.andWhere('p.source = :source', { source: p.source })
    }
    if (p.status) {
      queryBuilder.andWhere('p.p_status = :status', { status: p.status })
    }

    queryBuilder.orderBy('p.enter_date', 'DESC')

    const result = await queryBuilder.skip((page - 1) * pageSize).take(pageSize).getMany();
    this.formatResult(result)

    let total = await queryBuilder.getCount()
    total = Math.ceil(total / pageSize)
    return { result, total }
  }

  async findOne(pId: string) {
    const product = await this.product.findOne({ where: { pId, delete: false } })
    if (!product?.id) throw '未查询到该商品~'
    const result = [product]
    this.formatResult(result)
    return result[0]
  }

  async update(pId: string, updateProductDto: UpdateProductDto) {
    const product = await this.findOne(pId);
    if (!product?.id) throw '未查询到该商品~'
    updateProductDto.id = product.id
    updateProductDto.updateTime = new Date()
    return this.product.save(updateProductDto)
  }

  setStockByPId(pId: string, count: number) {
    return this.product.createQueryBuilder().update(Product).set({ stock: count, updateTime: new Date() }).where('p_id=:pId', { pId }).execute()
  }

  async remove(pId: string) {
    const product = await this.findOne(pId);
    if (!product?.id) throw '未查询到该商品~'
    product.delete = true
    return this.product.save(product)
  }

  getCategory() {
    const category = Utils.enumToArray(Category, getCategory)
    const source = Utils.enumToArray(Source, getSource)
    const status = Utils.enumToArray(Status, getStatus)
    const ip = this.ip.reduce((total, item) => total.push({ key: item, value: item }) && total, [])
    return { category, source, ip, status }
  }

  async getAllProductStock() {
    const sql = this.product.createQueryBuilder('p')
    sql.where('p.stock > 0')
    sql.andWhere('p.delete = :delete', { delete: false })
    return await sql.getMany()
  }
}
